﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Threading;
using System.Management;
using System.Net;
using System.ServiceProcess;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;

using RealTimePriceFetchService.BLL;
using RealTimePriceFetchService.Model;

using LanceZhang.StockLib;

namespace LanceZhang.DataFormatService
{
    public class Program : ServiceBase
    {
        private static int WorkThreads = Convert.ToInt32(ConfigurationManager.AppSettings["WorkThreads"]);
        private static int SleepTime = Convert.ToInt32(ConfigurationManager.AppSettings["SleepTime"]);
        private static int CheckTime = Convert.ToInt32(ConfigurationManager.AppSettings["CheckTime"]);
        private static int BusyTime = Convert.ToInt32(ConfigurationManager.AppSettings["BusyTime"]);
        private static int BatCount = Convert.ToInt32(ConfigurationManager.AppSettings["BatCount"]);
        private static bool LogToFile = ConfigurationManager.AppSettings["LogToFile"] == "1" ? true : false;
        private static bool EnableZip = ConfigurationManager.AppSettings["EnableZip"] == "1" ? true : false;
        private static bool EnableClear = ConfigurationManager.AppSettings["EnableClear"] == "1" ? true : false;
        private static string ServiceRealName = ConfigurationManager.AppSettings["ServiceName"];
        private static string ServiceDisPlayName = ConfigurationManager.AppSettings["ServiceDisPlayName"];
        private static string ServiceDescription = ConfigurationManager.AppSettings["ServiceDescription"];

        private static int FromHour = Convert.ToInt32(ConfigurationManager.AppSettings["FromHour"]);
        private static int ToHour = Convert.ToInt32(ConfigurationManager.AppSettings["ToHour"]);

        private static object lockobj = new object();

        private static string IP = GetIPAddress();
        private static string MAC = GetMacAddress();

        //服务所在路径
        private static string ServicePath = Application.ExecutablePath;
        private static string ServiceDirectory = Path.GetDirectoryName(ServicePath);

        //单线程
        private static Thread t;

        //公共StringBuilder
        private static StringBuilder sb = new StringBuilder();

        //股票查询字符串列表
        private static List<string> querylist = new List<string>();

        //调试模式开关
        private static int Debug = 0;

        //服务是否停止开关
        private static bool Stopped = false;

        private static bool CanStopped = false;

        //线程状态字典
        private static Dictionary<string, bool> DicStatus = new Dictionary<string, bool>();

        //业务逻辑对象
        private static RealTimeStockInfoBLL bllinfo = new RealTimeStockInfoBLL();
        private static StockTransferSubQueueBLL bllsubqueue = new StockTransferSubQueueBLL();

        //业务逻辑实体
        private static RealTimeStockInfoModel mod;

        //业务逻辑实体列表
        private static List<RealTimeStockInfoModel> modlist;
        private static List<StockTransferSubQueueModel> submodlist;

        //删除线程
        private static Thread threadCheck;
        //状态线程
        private static Thread threadStatus;

        //分隔符
        private static char[] c = { ',' };

        //时间标记
        private static DateTime t2100;
        private static DateTime t2330;


        #region 应用程序初始化
        private static void InitilizeCompoment()
        {
            Output("开始初始化", true);
            if (Debug == 1)
            {
                Console.Title = ServiceDisPlayName;
            }

            if (WorkThreads > 1)
            {
                WorkThreads = 1;
            }

            if (WorkThreads < 1)
            {
                WorkThreads = 1;
            }

            Output("IP：" + IP, ConsoleColor.Green, true);
            Output("MAC：" + MAC, ConsoleColor.Green, true);
            Output("开始处理数据", ConsoleColor.Green, true);


            t = new Thread(DecompressData);
            t.IsBackground = false;
            t.Start();

            //开启状态线程
            threadCheck = new Thread(CheckStatus);
            threadCheck.Start();

            //开启状态线程
            threadStatus = new Thread(TimeStatus);
            threadStatus.Start();

            if (Debug == 1)
            {
                Console.ReadLine();
                Output("启动完成", true);
            }
        }


        #endregion

        #region 数据处理逻辑

        private static void DecompressData()
        {
            while (true)
            {
                if (Stopped)
                {
                    CanStopped = true;

                    break;
                }

                try
                {
                    submodlist = bllsubqueue.GetTopModelList(BatCount);
                    if (submodlist == null)
                    {
                        Output("当前没有待处理的数据", ConsoleColor.Yellow, true);
                        Thread.Sleep(CheckTime);
                        continue;
                    }
                    //Output("开始处理1数据", ConsoleColor.Blue, true);
                }
                catch (Exception ee)
                {
                    Output("获取数据时发生错误：" + ee.Message, ConsoleColor.Red, true);
                }

                modlist = new List<RealTimeStockInfoModel>();
                foreach (StockTransferSubQueueModel m in submodlist)
                {
                    try
                    {
                        mod = GetData(m.RealTimeInfo);//构建对象
                    }
                    catch (Exception ee)
                    {
                        Output("处理数据时发生错误：" + ee.Message, ConsoleColor.Red, true);
                    }
                    modlist.Add(mod);//构建列表
                }

                foreach (RealTimeStockInfoModel n in modlist)
                {
                    try
                    {
                        bllinfo.Add(n);//插入数据
                    }
                    catch (Exception e)
                    {
                        Output("插入数据时发生错误：" + e.Message, ConsoleColor.Red, true);
                    }
                }

                foreach (StockTransferSubQueueModel m in submodlist)
                {
                    m.HasCopied = true;

                    try
                    {
                        bllsubqueue.Update(m);
                    }
                    catch (Exception eee)
                    {
                        Output("更新数据时发生错误：" + eee.Message, ConsoleColor.Red, true);
                    }
                }

                Thread.Sleep(SleepTime);
            }
        }

        private static void CheckStatus()
        {
            if (!EnableClear)
            {
                return;
            }

            while (true)
            {
                if (Stopped)
                {
                    CanStopped = true;

                    break;
                }

                try
                {
                    bllsubqueue.Clear();
                    //Output("清理了一批数据...", true);
                }
                catch (Exception e)
                {
                    Output("删除数据时发生错误：" + e.Message, ConsoleColor.Red, true);
                }

                Thread.Sleep(CheckTime);
            }
        }

        private static RealTimeStockInfoModel GetData(string info)
        {
            MatchCollection mc;

            Regex r = new Regex(@"(?<=\042).*(?=\042)"); //定义一个Regex对象实例
            mc = r.Matches(info);

            char[] c = { ',' };
            string[] results = (mc[0].Value).Split(c);

            #region comment
            /** 0："大秦铁路"，股票名字；
             * 1："27.55″，今日开盘价；
             * 2："27.25″，昨日收盘价；
             * 3："26.91″，当前价格；
             * 4："27.55″，今日最高价；
             * 5："26.20″，今日最低价；
             * 6："26.91″，竞买价，即"买一"报价；
             * 7："26.92″，竞卖价，即"卖一"报价；
             * 8："22114263″，成交的股票数，由于股票交易以一百股为基本单位，所以在使用时，通常把该值除以一百；
             * 9："589824680″，成交金额，单位为"元"，为了一目了然，通常以"万元"为成交金额的单位，所以通常把该值除以一万；
             * 10："4695″，"买一"申请4695股，即47手；
             * 11："26.91″，"买一"报价；
             * 12："57590″，"买二"
             * 13："26.90″，"买二"
             * 14："14700″，"买三"
             * 15："26.89″，"买三"
             * 16："14300″，"买四"
             * 17："26.88″，"买四"
             * 18："15100″，"买五"
             * 19："26.87″，"买五"
             * 20："3100″，"卖一"申报3100股，即31手；
             * 21："26.92″，"卖一"报价
             * (22, 23), (24, 25), (26,27), (28, 29)分别为"卖二"至"卖四的情况"
             * 30："2008-01-11″，日期；
             * 31："15:05:32″，时间；
             * */
            #endregion

            mod = new RealTimeStockInfoModel();
            mod.StockCode = GetStockCode(info);

            mod.CurrentCount = Convert.ToInt32(results[8]);
            mod.CurrentPrice = Convert.ToDecimal(results[3]);

            mod.Buy1Count = Convert.ToInt32(results[10]);
            mod.Buy1Price = Convert.ToDecimal(results[11]);
            mod.Buy2Count = Convert.ToInt32(results[12]);
            mod.Buy2Price = Convert.ToDecimal(results[13]);
            mod.Buy3Count = Convert.ToInt32(results[14]);
            mod.Buy3Price = Convert.ToDecimal(results[15]);
            mod.Buy4Count = Convert.ToInt32(results[16]);
            mod.Buy4Price = Convert.ToDecimal(results[17]);
            mod.Buy5Count = Convert.ToInt32(results[18]);
            mod.Buy5Price = Convert.ToDecimal(results[19]);

            mod.Sale1Count = Convert.ToInt32(results[20]);
            mod.Sale1Price = Convert.ToDecimal(results[21]);
            mod.Sale2Count = Convert.ToInt32(results[22]);
            mod.Sale2Price = Convert.ToDecimal(results[23]);
            mod.Sale3Count = Convert.ToInt32(results[24]);
            mod.Sale3Price = Convert.ToDecimal(results[25]);
            mod.Sale4Count = Convert.ToInt32(results[26]);
            mod.Sale4Price = Convert.ToDecimal(results[27]);
            mod.Sale5Count = Convert.ToInt32(results[28]);
            mod.Sale5Price = Convert.ToDecimal(results[29]);

            mod.CurrentTime = Convert.ToDateTime(results[30] + " " + results[31]);

            return mod;
        }

        private static int GetStockCode(string info)
        {
            MatchCollection mc;

            Regex r = new Regex(@"\d{6}(?=[=])"); //定义一个Regex对象实例
            mc = r.Matches(info);
            return Convert.ToInt32(mc[0].Value); //将匹配的字符串添在字符串数组中
        }

        #endregion

        #region 应用程序入口
        static void Main(string[] args)
        {
            Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(Program_UnhandledException);
            Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);

            bool exists = ServiceControl.CheckService(ServiceRealName);

            if (args.Length == 0)
            {
                ServiceBase.Run(new ServiceBase[] { new Program() });
            }
            else
            {
                string parm = args[0].ToLower();

                switch (parm)
                {
                    case "-debug":
                    case "/debug":

                        Debug = 1;

                        if (exists)
                        {
                            ServiceControllerStatus status = ServiceControl.GetServiceStatus(ServiceRealName);

                            if (status != ServiceControllerStatus.Stopped)
                            {
                                Console.WriteLine(GetDateTime() + ServiceRealName + " 服务正在运行，无法进入调试状态。请先停止该服务");
                                Console.WriteLine(GetDateTime() + "请关闭本窗体");
                                Console.ReadLine();
                            }
                            else
                            {
                                InitilizeCompoment();
                            }
                        }
                        else
                        {
                            InitilizeCompoment();
                        }


                        break;

                    case "-install":
                    case "-setup":
                    case "/install":
                    case "/setup":

                        if (exists)
                        {
                            Console.WriteLine(GetDateTime() + ServiceRealName + " 服务已经存在，如果您想升级服务，请先卸载该服务");
                            Console.WriteLine(GetDateTime() + "请关闭本窗体");
                            Console.ReadLine();
                        }
                        else
                        {
                            Console.WriteLine(GetDateTime() + ServicePath);

                            bool result = ServiceControl.InstallService(ServicePath, ServiceRealName, ServiceDisPlayName, ServiceDescription);

                            if (result)
                            {
                                Console.WriteLine(GetDateTime() + "服务安装成功");
                                Console.WriteLine(GetDateTime() + "正在启动服务...");

                                ServiceControl.StartService(ServiceRealName);

                                while (!(ServiceControl.GetServiceStatus(ServiceRealName) == ServiceControllerStatus.Running))
                                {
                                    Thread.Sleep(SleepTime);
                                }

                                Console.WriteLine(GetDateTime() + "服务已经启动");
                            }
                            else
                            {
                                Console.WriteLine(GetDateTime() + "服务安装失败");
                            }

                            Console.WriteLine(GetDateTime() + "请关闭本窗体");
                            Console.ReadLine();
                        }
                        break;

                    case "-uninstall":
                    case "-remove":
                    case "/uninstall":
                    case "/remove":

                        if (!exists)
                        {
                            Console.WriteLine(GetDateTime() + ServiceRealName + " 服务尚未安装");
                        }
                        else
                        {
                            bool result = ServiceControl.UnInstallService(ServiceRealName);

                            if (!result)
                            {
                                Console.WriteLine(GetDateTime() + "服务卸载失败");
                            }
                            else
                            {
                                Console.WriteLine(GetDateTime() + "服务卸载成功");
                            }
                        }

                        Console.WriteLine(GetDateTime() + "请关闭本窗体");
                        Console.ReadLine();

                        break;

                }

            }
        }

        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            Output("未处理A：" + e.Exception.Message, ConsoleColor.Red, true);
        }

        static void Program_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is System.Exception)
            {
                Output("未处理P：" + ((System.Exception)e.ExceptionObject).Message, ConsoleColor.Red, true);
            }

        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {

            }

            base.Dispose(disposing);
        }

        public Program()
        {
            base.ServiceName = ServiceRealName;
            base.AutoLog = true;
        }

        #endregion

        #region 初始化服务设置
        protected override void OnStart(string[] args)
        {
            InitilizeCompoment();
        }

        protected override void OnStop()
        {

            Stopped = true;

            try
            {
                if (WorkThreads == 1)
                {
                    while (!CanStopped)
                    {
                        Thread.Sleep(SleepTime);
                    }
                }
                else
                {
                    while (!AllStop())
                    {
                        Thread.Sleep(SleepTime);
                    }
                }
            }
            catch
            {
            }

        }

        /// <summary>
        /// 判断工作线程是否已经都停止了
        /// </summary>
        /// <returns></returns>
        private static bool AllStop()
        {
            try
            {
                lock (lockobj)
                {
                    foreach (bool value in DicStatus.Values)
                    {
                        if (!value)
                        {
                            return false;
                        }
                    }
                }

                return true;
            }
            catch
            {
                return false;
            }
        }
        #endregion

        #region 辅助逻辑

        #region 调试

        private static string GetDateTime()
        {
            return "[" + DateTime.Now.ToString("HH:mm:ss") + "] ";
        }

        private static void Output(string msg)
        {
            lock (lockobj)
            {
                if (Debug == 1)
                {
                    Console.WriteLine(GetDateTime() + msg);
                }
            }
        }

        private static void Output(string msg, bool log)
        {
            lock (lockobj)
            {
                if (Debug == 1)
                {
                    Console.WriteLine(GetDateTime() + msg);
                }

                if (log)
                {
                    if (LogToFile)
                    {
                        Log.WriteToFile(ServiceDirectory + @"\log_" + DateTime.Now.ToString("yyyyMMdd") + ".txt", GetDateTime() + msg);
                    }
                }
            }
        }

        private static void Output(string msg, ConsoleColor color)
        {
            lock (lockobj)
            {
                if (Debug == 1)
                {
                    Console.ForegroundColor = color;
                    Console.WriteLine(GetDateTime() + msg);
                    Console.ResetColor();
                }
            }
        }

        private static void Output(string msg, ConsoleColor color, bool log)
        {
            lock (lockobj)
            {
                if (Debug == 1)
                {
                    Console.ForegroundColor = color;
                    Console.WriteLine(GetDateTime() + msg);
                    Console.ResetColor();
                }

                if (log)
                {
                    if (LogToFile)
                    {
                        Log.WriteToFile(ServiceDirectory + @"\log_" + DateTime.Now.ToString("yyyyMMdd") + ".txt", GetDateTime() + msg);
                    }
                }
            }
        }

        #endregion

        #region 获得IP地址
        private static string GetIPAddress()
        {

            IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());

            string ip = string.Empty;

            for (int i = 0; i < ips.Length; i++)
            {
                ip += ips[i].ToString() + ",";
            }

            if (ip != string.Empty)
            {
                ip = ip.Substring(0, ip.Length - 1);
            }

            return ip;

            /*
            string ip = string.Empty;
            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                if ((bool)mo["IPEnabled"] == true)
                {
                    string[] ipaddresses = (string[])mo["IPAddress"];

                    for (int i = 0; i < ipaddresses.Length; i++)
                    {
                        ip += ipaddresses[i].ToString() + ",";
                    }
                }
            }

            if (ip != string.Empty)
            {
                ip = ip.Substring(0, ip.Length - 1);
            }

            return ip;
           */

        }
        #endregion

        #region 获得MAC
        private static string GetMacAddress()
        {
            ManagementClass adapters = new ManagementClass("Win32_NetworkAdapterConfiguration");
            string MACAddress = string.Empty;
            foreach (ManagementObject adapter in adapters.GetInstances())
            {
                if ((bool)adapter["IPEnabled"] == true)
                {
                    MACAddress = adapter.Properties["MACAddress"].Value.ToString();
                    MACAddress += ",";
                }
            }

            //去除最后一个,号
            if (MACAddress != string.Empty)
            {
                MACAddress = MACAddress.Substring(0, MACAddress.Length - 1);
            }

            return MACAddress;
        }
        #endregion

        #endregion

        #region 时间状态控制

        /// <summary>
        /// 接收状态
        /// </summary>
        private static void TimeStatus()
        {

            while (true)
            {
                if (isBusyTime())
                {
                    Output("目前系统繁忙，空闲时再执行", ConsoleColor.Green, true);
                    Stopped = true;
                }
                else
                {
                    if (Stopped)
                    {
                        Output("目前系统空闲，执行操作", ConsoleColor.Green, true);
                        Stopped = false;
                        InitilizeCompoment();
                    }
                }

                Thread.Sleep(BusyTime);
            }
        }

        /// <summary>
        /// 当前时间是否是繁忙时间
        /// </summary>
        /// <example>21：00~23：30处理数据</example>
        /// <returns></returns>
        private static bool isBusyTime()
        {
            t2100 = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, FromHour, 0, 0);
            t2330 = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, ToHour, 0, 0);

            if ((DateTime.Now > t2100) && (DateTime.Now < t2330))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        #endregion

    }
}
